include(AwsLibFuzzer)
include(AwsTestHarness)
enable_testing()

file(GLOB META_TEST_SRC "assert_test.c")
file(GLOB TEST_BASE_SRC "*.c")
file(GLOB TEST_LOGGING_SRC "logging/*.c")
file(GLOB TEST_SRC ${TEST_BASE_SRC} ${TEST_LOGGING_SRC})
list(REMOVE_ITEM TEST_SRC ${META_TEST_SRC})
file(GLOB TEST_BASE_HDRS "*.h")
file(GLOB TEST_LOGGING_HDRS "logging/*.h")
file(GLOB TEST_HDRS ${TEST_BASE_HDRS} ${TEST_LOGGING_HDRS})
file(GLOB TESTS ${TEST_HDRS} ${TEST_SRC})

set(METATEST_BINARY_NAME ${PROJECT_NAME}-assert-tests)

if (NOT LEGACY_COMPILER_SUPPORT)
    add_executable(${METATEST_BINARY_NAME} ${META_TEST_SRC})
    aws_set_common_properties(${METATEST_BINARY_NAME} NO_WEXTRA NO_PEDANTIC)
    aws_add_sanitizers(${METATEST_BINARY_NAME} ${${PROJECT_NAME}_SANITIZERS})
    target_link_libraries(${METATEST_BINARY_NAME} PRIVATE ${PROJECT_NAME})

    target_compile_definitions(${METATEST_BINARY_NAME} PRIVATE AWS_UNSTABLE_TESTING_API=1)
    target_include_directories(${METATEST_BINARY_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR})
    if(MSVC)
        target_compile_definitions(${METATEST_BINARY_NAME} PRIVATE "-D_CRT_SECURE_NO_WARNINGS")
    endif()

    add_test(assert_test ${METATEST_BINARY_NAME} ${CMAKE_CURRENT_BINARY_DIR}/metatest.tmp)
endif()

add_test_case(raise_errors_test)
add_test_case(reset_errors_test)
add_test_case(error_callback_test)
add_test_case(unknown_error_code_in_slot_test)
add_test_case(unknown_error_code_no_slot_test)
add_test_case(unknown_error_code_range_too_large_test)
add_test_case(aws_load_error_strings_test)
add_test_case(aws_assume_compiles_test)

add_test_case(thread_creation_join_test)
add_test_case(thread_atexit_test)
add_test_case(test_managed_thread_join)
add_test_case(test_managed_thread_join_timeout)

add_test_case(mutex_aquire_release_test)
add_test_case(mutex_is_actually_mutex_test)
add_test_case(mutex_try_lock_is_correct_test)

add_test_case(conditional_notify_one)
add_test_case(conditional_notify_all)

add_test_case(error_code_cross_thread_test)

add_test_case(high_res_clock_increments_test)
add_test_case(sys_clock_increments_test)
add_test_case(test_sec_and_millis_conversions)
add_test_case(test_sec_and_micros_conversions)
add_test_case(test_sec_and_nanos_conversions)
add_test_case(test_milli_and_micros_conversion)
add_test_case(test_milli_and_nanos_conversion)
add_test_case(test_micro_and_nanos_conversion)
add_test_case(test_precision_loss_remainders_conversion)
add_test_case(test_overflow_conversion)
add_test_case(test_old_overflow_cases)

add_test_case(array_list_order_push_back_pop_front_test)
add_test_case(array_list_order_push_back_pop_back_test)
add_test_case(array_list_pop_front_n_test)
add_test_case(array_list_erase_test)
add_test_case(array_list_exponential_mem_model_test)
add_test_case(array_list_exponential_mem_model_iteration_test)
add_test_case(array_list_set_at_overwrite_safety)
add_test_case(array_list_iteration_by_ptr_test)
add_test_case(array_list_iteration_test)
add_test_case(array_list_preallocated_iteration_test)
add_test_case(array_list_preallocated_push_test)
add_test_case(array_list_shrink_to_fit_test)
add_test_case(array_list_shrink_to_fit_static_test)
add_test_case(array_list_clear_test)
add_test_case(array_list_copy_test)
add_test_case(array_list_swap_contents_test)
add_test_case(array_list_not_enough_space_test)
add_test_case(array_list_not_enough_space_test_failure)
add_test_case(array_list_of_strings_sort)
add_test_case(array_list_empty_sort)
add_test_case(priority_queue_push_pop_order_test)
add_test_case(priority_queue_random_values_test)
add_test_case(priority_queue_size_and_capacity_test)
add_test_case(priority_queue_remove_root_test)
add_test_case(priority_queue_remove_leaf_test)
add_test_case(priority_queue_remove_interior_sift_up_test)
add_test_case(priority_queue_remove_interior_sift_down_test)

add_test_case(linked_list_push_back_pop_front)
add_test_case(linked_list_push_front_pop_back)
add_test_case(linked_list_swap_nodes)
add_test_case(linked_list_iteration)
add_test_case(linked_list_reverse_iteration)
add_test_case(linked_list_swap_contents)
add_test_case(linked_list_move_all_back)
add_test_case(linked_list_move_all_front)

add_test_case(hex_encoding_test_case_empty_test)
add_test_case(hex_encoding_test_case_f_test)
add_test_case(hex_encoding_test_case_fo_test)
add_test_case(hex_encoding_test_case_foo_test)
add_test_case(hex_encoding_test_case_foob_test)
add_test_case(hex_encoding_test_case_fooba_test)
add_test_case(hex_encoding_test_case_foobar_test)
add_test_case(hex_encoding_test_case_missing_leading_zero)
add_test_case(hex_encoding_invalid_buffer_size_test)
add_test_case(hex_encoding_highbyte_string_test)
add_test_case(hex_encoding_overflow_test)
add_test_case(hex_encoding_invalid_string_test)
add_test_case(hex_encoding_append_dynamic_test_case_empty)
add_test_case(hex_encoding_append_dynamic_test_case_fooba)
add_test_case(base64_encoding_test_case_empty_test)
add_test_case(base64_encoding_test_case_f_test)
add_test_case(base64_encoding_test_case_fo_test)
add_test_case(base64_encoding_test_case_foo_test)
add_test_case(base64_encoding_test_case_foob_test)
add_test_case(base64_encoding_test_case_fooba_test)
add_test_case(base64_encoding_test_case_foobar_test)
add_test_case(base64_encoding_test_case_32bytes_test)
add_test_case(base64_encoding_buffer_size_too_small_test)
add_test_case(base64_encoding_buffer_size_overflow_test)
add_test_case(base64_encoding_buffer_size_invalid_test)
add_test_case(base64_encoding_invalid_buffer_test)
add_test_case(base64_encoding_highbyte_string_test)
add_test_case(base64_encoding_invalid_padding_test)
add_test_case(base64_encoding_test_zeros)
add_test_case(base64_encoding_test_roundtrip)
add_test_case(base64_encoding_test_all_values)
add_test_case(uint64_buffer_test)
add_test_case(uint64_buffer_non_aligned_test)
add_test_case(uint32_buffer_test)
add_test_case(uint32_buffer_non_aligned_test)
add_test_case(uint24_buffer_test)
add_test_case(uint24_buffer_non_aligned_test)
add_test_case(uint16_buffer_test)
add_test_case(uint16_buffer_non_aligned_test)
add_test_case(uint16_buffer_signed_positive_test)
add_test_case(uint16_buffer_signed_negative_test)
add_test_case(text_encoding_utf8)
add_test_case(text_encoding_utf16)
add_test_case(text_encoding_ascii)
add_test_case(text_encoding_is_utf8)

add_test_case(scheduler_cleanup_cancellation)
add_test_case(scheduler_ordering_test)
add_test_case(scheduler_pops_task_late_test)
add_test_case(scheduler_has_tasks_test)
add_test_case(scheduler_reentrant_safe)
add_test_case(scheduler_cleanup_reentrants)
add_test_case(scheduler_oom_still_works)
add_test_case(scheduler_schedule_cancellation)
add_test_case(scheduler_cleanup_idempotent)
add_test_case(scheduler_oom_during_init)
add_test_case(scheduler_task_delete_on_run)

add_test_case(test_hash_table_create_find)
add_test_case(test_hash_table_string_create_find)
add_test_case(test_hash_table_put)
add_test_case(test_hash_table_put_null_dtor)
add_test_case(test_hash_table_swap_move)
add_test_case(test_hash_table_string_clean_up)
add_test_case(test_hash_table_hash_collision)
add_test_case(test_hash_table_hash_overwrite)
add_test_case(test_hash_table_hash_remove)
add_test_case(test_hash_table_hash_clear_allows_cleanup)
add_test_case(test_hash_table_on_resize_returns_correct_entry)
add_test_case(test_hash_table_foreach)
add_test_case(test_hash_table_iter)
add_test_case(test_hash_table_empty_iter)
add_test_case(test_hash_table_iter_detail)
add_test_case(test_hash_table_eq)
add_test_case(test_hash_churn)
add_test_case(test_hash_table_cleanup_idempotent)
add_test_case(test_hash_table_byte_cursor_create_find)
add_test_case(test_hash_combine)

add_test_case(test_linked_hash_table_preserves_insertion_order)
add_test_case(test_linked_hash_table_entries_cleanup)
add_test_case(test_linked_hash_table_entries_overwrite)

add_test_case(test_lru_cache_overflow_static_members)
add_test_case(test_lru_cache_lru_ness_static_members)
add_test_case(test_lru_cache_element_access_members)
add_test_case(test_fifo_cache_overflow_static_members)
add_test_case(test_lifo_cache_overflow_static_members)
add_test_case(test_cache_entries_cleanup)
add_test_case(test_cache_entries_overwrite)

add_test_case(test_is_power_of_two)
add_test_case(test_round_up_to_power_of_two)
add_test_case(test_mul_size_checked)
add_test_case(test_mul_size_saturating)
add_test_case(test_mul_u32_checked)
add_test_case(test_mul_u32_saturating)
add_test_case(test_mul_u64_checked)
add_test_case(test_mul_u64_saturating)
add_test_case(test_add_size_checked)
add_test_case(test_aws_add_size_checked_varargs)
add_test_case(test_add_size_saturating)
add_test_case(test_add_u32_checked)
add_test_case(test_add_u32_saturating)
add_test_case(test_add_u64_checked)
add_test_case(test_add_u64_saturating)
add_test_case(test_min_max)

add_test_case(nospec_index_test)
add_test_case(test_byte_cursor_advance)
add_test_case(test_byte_cursor_advance_nospec)

add_test_case(byte_cursor_write_tests)
add_test_case(byte_cursor_read_tests)
add_test_case(byte_cursor_limit_tests)
add_test_case(test_byte_cursor_read_hex_u8)
add_test_case(test_byte_cursor_right_trim_empty)
add_test_case(test_byte_cursor_right_trim_all_whitespace)
add_test_case(test_byte_cursor_right_trim_basic)
add_test_case(test_byte_cursor_left_trim_empty)
add_test_case(test_byte_cursor_left_trim_all_whitespace)
add_test_case(test_byte_cursor_left_trim_basic)
add_test_case(test_byte_cursor_trim_basic)

add_test_case(string_tests)
add_test_case(binary_string_test)
add_test_case(string_compare_test)
add_test_case(string_destroy_secure_test)
add_test_case(secure_strlen_test)

add_test_case(test_char_split_happy_path)
add_test_case(test_char_split_ends_with_token)
add_test_case(test_char_split_token_not_present)
add_test_case(test_char_split_empty)
add_test_case(test_char_split_zeroed)
add_test_case(test_char_split_adj_tokens)
add_test_case(test_char_split_begins_with_token)
add_test_case(test_char_split_with_max_splits)
add_test_case(test_char_split_output_too_small)
add_test_case(test_buffer_cat)
add_test_case(test_buffer_cat_dest_too_small)
add_test_case(test_buffer_cpy)
add_test_case(test_buffer_cpy_dest_too_small)
add_test_case(test_buffer_cpy_offsets)
add_test_case(test_buffer_cpy_offsets_dest_too_small)
add_test_case(test_buffer_eq)
add_test_case(test_buffer_eq_same_content_different_len)
add_test_case(test_buffer_eq_null_internal_byte_buffer)
add_test_case(test_buffer_init_copy)
add_test_case(test_buffer_init_copy_null_buffer)
add_test_case(test_buffer_advance)
add_test_case(test_buffer_printf)
add_test_case(test_array_eq)
add_test_case(test_array_eq_ignore_case)
add_test_case(test_array_eq_c_str)
add_test_case(test_array_eq_c_str_ignore_case)
add_test_case(test_array_hash_ignore_case)
add_test_case(test_byte_buf_write_to_capacity)
add_test_case(test_byte_buf_init_cache_and_update_cursors)
add_test_case(test_byte_buf_append_and_update_fail)
add_test_case(test_byte_buf_append_and_update_success)
add_test_case(test_byte_buf_append_dynamic)
add_test_case(test_byte_buf_append_byte)
add_test_case(test_byte_buf_append_lookup_success)
add_test_case(test_byte_buf_append_lookup_failure)
add_test_case(test_byte_buf_reserve)
add_test_case(test_byte_buf_reserve_relative)
add_test_case(test_byte_buf_reset)
add_test_case(test_byte_cursor_compare_lexical)
add_test_case(test_byte_cursor_compare_lookup)
add_test_case(test_isalnum)
add_test_case(test_isalpha)
add_test_case(test_isdigit)
add_test_case(test_isxdigit)
add_test_case(test_isspace)

add_test_case(byte_swap_test)

if (HAVE_AVX2_INTRINSICS)
    add_test_case(alignment32_test)
else()
    add_test_case(alignment16_test)
endif()


add_test_case(test_cpu_count_at_least_works_superficially)
add_test_case(test_stack_trace_decoding)
add_test_case(test_platform_build_os)
add_test_case(test_sanity_check_numa_discovery)

add_test_case(test_realloc_fallback)
add_test_case(test_realloc_fallback_oom)
add_test_case(test_realloc_passthrough)
add_test_case(test_realloc_passthrough_oom)
add_test_case(test_cf_allocator_wrapper)
add_test_case(test_acquire_many)
add_test_case(test_alloc_nothing)
add_test_case(sba_alloc_free_once)
add_test_case(sba_random_allocs_and_frees)
add_test_case(sba_random_reallocs)
add_test_case(sba_threaded_allocs_and_frees)
add_test_case(sba_threaded_reallocs)
add_test_case(sba_churn)

add_test_case(test_memtrace_none)
add_test_case(test_memtrace_count)
add_test_case(test_memtrace_stacks)
add_test_case(test_memtrace_midstream)

add_test_case(test_calloc_override)
add_test_case(test_calloc_fallback_from_default_allocator)
add_test_case(test_calloc_fallback_from_given)
add_test_case(test_calloc_from_default_allocator)
add_test_case(test_calloc_from_given_allocator)

add_test_case(timebomb_allocator)

add_test_case(rw_lock_aquire_release_test)
add_test_case(rw_lock_is_actually_rw_lock_test)
add_test_case(rw_lock_many_readers_test)
add_test_case(test_secure_zero)
add_test_case(test_buffer_secure_zero)
add_test_case(test_buffer_clean_up_secure)
add_test_case(is_zeroed)

add_test_case(atomics_semantics)
add_test_case(atomics_semantics_implicit)
add_test_case(atomics_static_init)

add_test_case(atomics_acquire_to_release_one_direction)
add_test_case(atomics_acquire_to_release_mixed)

add_test_case(rfc822_utc_parsing)
add_test_case(rfc822_utc_parsing_auto_detect)
add_test_case(rfc822_local_time_east_of_gmt_parsing)
add_test_case(rfc822_local_time_west_of_gmt_parsing)
add_test_case(rfc822_utc_two_digit_year_parsing)
add_test_case(rfc822_utc_no_dow_parsing)
add_test_case(rfc822_utc_dos_prevented)
add_test_case(rfc822_invalid_format)
add_test_case(rfc822_invalid_tz)
add_test_case(rfc822_invalid_auto_format)
add_test_case(iso8601_utc_parsing)
add_test_case(iso8601_basic_utc_parsing)
add_test_case(iso8601_utc_parsing_auto_detect)
add_test_case(iso8601_basic_utc_parsing_auto_detect)
add_test_case(iso8601_date_only_parsing)
add_test_case(iso8601_basic_date_only_parsing)
add_test_case(iso8601_utc_no_colon_parsing)
add_test_case(iso8601_utc_dos_prevented)
add_test_case(iso8601_invalid_format)
add_test_case(iso8601_invalid_auto_format)
add_test_case(unix_epoch_parsing)
add_test_case(millis_parsing)

add_test_case(device_rand_u64_distribution)
add_test_case(device_rand_u32_distribution)
add_test_case(device_rand_u16_distribution)
add_test_case(device_rand_buffer_distribution)

add_test_case(uuid_string)
add_test_case(prefilled_uuid_string)
add_test_case(uuid_string_short_buffer)
add_test_case(uuid_string_parse)
add_test_case(uuid_string_parse_too_short)
add_test_case(uuid_string_parse_malformed)

add_test_case(test_environment_functions)

add_test_case(short_argument_parse)
add_test_case(long_argument_parse)
add_test_case(unqualified_argument_parse)
add_test_case(unknown_argument_parse)

add_test_case(ring_buffer_1_to_1_acquire_release_wraps_test)
add_test_case(ring_buffer_release_after_full_test)
add_test_case(ring_buffer_acquire_up_to_test)
add_test_case(ring_buffer_acquire_tail_always_chases_head_test)
add_test_case(ring_buffer_acquire_multi_threaded_test)
add_test_case(ring_buffer_acquire_up_to_multi_threaded_test)
add_test_case(ring_buffer_allocator_test)

add_test_case(string_to_log_level_success_test)
add_test_case(string_to_log_level_failure_test)
if (NOT ANDROID)
    add_test_case(test_logging_filter_at_AWS_LL_NONE_s_logf_all_levels)
    add_test_case(test_logging_filter_at_AWS_LL_FATAL_s_logf_all_levels)
    add_test_case(test_logging_filter_at_AWS_LL_ERROR_s_logf_all_levels)
    add_test_case(test_logging_filter_at_AWS_LL_WARN_s_logf_all_levels)
    add_test_case(test_logging_filter_at_AWS_LL_INFO_s_logf_all_levels)
    add_test_case(test_logging_filter_at_AWS_LL_DEBUG_s_logf_all_levels)
    add_test_case(test_logging_filter_at_AWS_LL_TRACE_s_logf_all_levels)

    add_test_case(test_logging_filter_at_AWS_LL_TRACE_s_logf_all_levels_trace_cutoff)
    add_test_case(test_logging_filter_at_AWS_LL_TRACE_s_logf_all_levels_debug_cutoff)
    add_test_case(test_logging_filter_at_AWS_LL_TRACE_s_logf_all_levels_info_cutoff)
    add_test_case(test_logging_filter_at_AWS_LL_TRACE_s_logf_all_levels_warn_cutoff)
    add_test_case(test_logging_filter_at_AWS_LL_TRACE_s_logf_all_levels_error_cutoff)
    add_test_case(test_logging_filter_at_AWS_LL_TRACE_s_logf_all_levels_fatal_cutoff)
    add_test_case(test_logging_filter_at_AWS_LL_TRACE_s_logf_all_levels_none_cutoff)

    add_test_case(test_log_formatter_s_formatter_empty_case)
    add_test_case(test_log_formatter_s_formatter_simple_case)
    add_test_case(test_log_formatter_s_formatter_number_case)
    add_test_case(test_log_formatter_s_formatter_string_case)
    add_test_case(test_log_formatter_s_formatter_newline_case)

    add_test_case(test_log_writer_simple_file_test)
    add_test_case(test_log_writer_existing_file_test)
    add_test_case(test_log_writer_bad_file_test)

    add_test_case(test_foreground_log_channel_single_line)
    add_test_case(test_foreground_log_channel_numbers)
    add_test_case(test_foreground_log_channel_words)
    add_test_case(test_foreground_log_channel_all)
    add_test_case(test_background_log_channel_single_line)
    add_test_case(test_background_log_channel_numbers)
    add_test_case(test_background_log_channel_words)
    add_test_case(test_background_log_channel_all)

    add_test_case(test_pipeline_logger_unformatted_test)
    add_test_case(test_pipeline_logger_formatted_test)

    add_test_case(dynamic_log_level_change_test)
endif() # ANDROID

add_test_case(get_pid_sanity_check_test)
add_test_case(max_io_handles_sanity_check_test)
add_test_case(run_command_test_success)
add_test_case(run_command_test_bad_command)

add_test_case(parse_resource_name_test)
add_test_case(parse_resource_name_failures_test)
add_test_case(resource_name_tostring_test)
add_test_case(resource_name_tostring_failure_test)
add_test_case(resource_name_length_test)

add_test_case(cpuid_test)

add_test_case(xml_parser_root_with_text)
add_test_case(xml_parser_child_with_text)
add_test_case(xml_parser_siblings_with_text)
add_test_case(xml_parser_preamble_and_attributes)
add_test_case(xml_parser_nested_node_same_name_test)
add_test_case(xml_parser_nested_node_deep_recursion_test)
add_test_case(xml_parser_too_many_attributes_test)
add_test_case(xml_parser_name_too_long_test)

add_test_case(test_thread_scheduler_ordering)
add_test_case(test_thread_scheduler_happy_path_cancellation)
add_test_case(test_scheduler_cancellation_for_pending_scheduled_task)

generate_test_driver(${PROJECT_NAME}-tests)

if (NOT MSVC AND NOT LEGACY_COMPILER_SUPPORT)
    #we have some tests here that purposely overflow
    target_compile_options(${PROJECT_NAME}-tests PRIVATE -Wno-overflow)
endif()

if (MSVC)
    target_compile_options(${PROJECT_NAME}-tests PRIVATE -D_CRT_SECURE_NO_WARNINGS)
endif()

file(GLOB FUZZ_TESTS    "fuzz/*.c")
aws_add_fuzz_tests("${FUZZ_TESTS}" "" "")

# Resources to use for testing.
add_custom_command(TARGET ${PROJECT_NAME}-tests PRE_BUILD
        COMMAND ${CMAKE_COMMAND} -E copy_directory
        ${CMAKE_CURRENT_SOURCE_DIR}/resources $<TARGET_FILE_DIR:${PROJECT_NAME}-tests>)
